package com.chipcoo.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.SymbolTable;
import com.chipcoo.IUserPrincipal;
import com.chipcoo.ResponseResult;
import com.chipcoo.models.*;
import com.chipcoo.models.gen.Finger;
import com.chipcoo.services.ConfService;
import com.chipcoo.services.UserService;
import com.chipcoo.shiro.session.mgt.UserSession;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.session.ProxiedSession;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;

import static com.chipcoo.utils.StringUtils.isEmpty;

/**
 * 安全相关实用类,尽量做到跟容器无关
 */
public final class SecurityUtils{
    public static int parseLoginErr(Exception ex) {
        if (null == ex) return 0;
        int errCode = 0;
        if (ex instanceof UnknownAccountException
                || ex instanceof IncorrectCredentialsException) {
            errCode = ResponseResult.ERR_VAL;
        } else if (ex instanceof ExpiredCredentialsException) {
            errCode = ResponseResult.EXPIRED;
        } else if (ex instanceof LockedAccountException) {
            errCode = ResponseResult.LOCKED;
        } else if (ex instanceof DisabledAccountException
                || ex instanceof LockedAccountException) {
            errCode = ResponseResult.DISABLED;
        } else if (ex instanceof AccountException
                || ex instanceof UnsupportedTokenException) {
            errCode = ResponseResult.ERR_FORMAT; //账号不存在或格式错误
        } else {
            errCode = ResponseResult.ERR_SYSTEM;
            //message = "系统出现点问题，请稍后再试！";
            ex.printStackTrace(); // 输出到控制台
        }

        return errCode;
    }
    private final static  String SESSION_KEY_ERR_COUNT = "SESSION_I_TRIED_COUNT";
    private final static  String SESSION_KEY_CURRENT_FINGER = "SESSION_CURRENT_FINGER";
    public static Session getSession(boolean create){
        Session s =  org.apache.shiro.SecurityUtils.getSubject().getSession(create);

        return s;
    }

    public static void increaseSessionError(){
        Session  session = getSession(false);
        if(null!=session){
            Object tried = session.getAttribute(SESSION_KEY_ERR_COUNT);
            if(null==tried) session.setAttribute(SESSION_KEY_ERR_COUNT,1);
            else session.setAttribute(SESSION_KEY_ERR_COUNT,((Integer)tried)+1);
        }
    }
    public static void resetSessionError(){
        Session session = SecurityUtils.getSession(false);
        if(null!=session) {
            session.removeAttribute(SESSION_KEY_ERR_COUNT);
        }
    }
    public static int getSessionError(){
        Session  session = getSession(false);
        if(null!=session){
            Object tried = session.getAttribute(SESSION_KEY_ERR_COUNT);
            if(null==tried) return 0;
            else return (Integer)tried;
        }
        return  0;
    }

    public static Finger getCurrentFinger() {
        Session session =getSession(false);
        if (null != session) {
            Object finger= session.getAttribute(SESSION_KEY_CURRENT_FINGER);
            if(null!=finger) {
                return (Finger) finger;
            }else{
                System.err.printf( "=======getCurrentFinger %s======\r\n",session);
                if(session instanceof UserSession){
                    UserSession userSession = (UserSession) session;
                    if(!StringUtils.isEmpty(userSession.getFingerID())){
                        Finger fingerModel = BeanUtils.getBean("confService",ConfService.class).getDeviceFinger(userSession.getFingerID());
                        setCurrentFinger(fingerModel);
                        return fingerModel;
                    }
                }
            }
        }

        return null;
    }
    public static void setCurrentFinger(Finger finger){
        Session session = getSession(null!=finger);
        if (null != session) {
            if(null!=finger) {
                session.setAttribute(SESSION_KEY_CURRENT_FINGER, finger);
                Object o_finger_id =session.getAttribute("finger_id");
                if(null==o_finger_id || !finger.getId().equals(o_finger_id.toString())) {
                    session.setAttribute("finger_id",finger.getId());
                }
            }else {
                if(null!=session.getAttribute("SESSION_KEY_CURRENT_FINGER"))
                    session.removeAttribute(SESSION_KEY_CURRENT_FINGER);
                Object o_finger_id =session.getAttribute("finger_id");
                if(null!=o_finger_id) session.removeAttribute("finger_id");
            }

        }
    }
    public static IUserPrincipal getCurrentUser(){

        Object o = org.apache.shiro.SecurityUtils.getSubject().getPrincipal();
        if (null!=o && o instanceof IUserPrincipal)
            return (IUserPrincipal) o;

        return  null;

    }
    public static boolean isAuthenticated(){
        return org.apache.shiro.SecurityUtils.getSubject().isAuthenticated();
    }


    public static WxMpOAuth2AccessToken getWxMpOAuth2AccessToken(){
        Session session = getSession(false);
        if(null==session) return null;

        Object o = session.getAttribute("WX_OAUTH2_ACCESS_TOKEN");

        if(null==o) return  null;

        if(o instanceof WxMpOAuth2AccessToken) return (WxMpOAuth2AccessToken)o;

        return null;
    }
    public static void setWxMpOAuth2AccessToken(WxMpOAuth2AccessToken token){
        Session session = getSession(false);
        if(null!=session){
            if(null!=token) session.setAttribute("WX_OAUTH2_ACCESS_TOKEN",token);
            else  session.removeAttribute("WX_OAUTH2_ACCESS_TOKEN");
        }
    }

    public static Finger parseDeviceFinger(String userAgent, String hashedID, JSONObject jsonObject){
        if(isEmpty(userAgent)) return null;
        Finger finger= new Finger();
        finger.setId(hashedID);

        IdentifyVersion identifyVersion = App.parseUserAgent(userAgent);
        if(null!=identifyVersion){
            finger.setApp(identifyVersion.getId());
            finger.setAppVersion(identifyVersion.getVersion());
        }

        identifyVersion = OS.parseUserAgent(userAgent);
        if(null!=identifyVersion){
            finger.setOs(identifyVersion.getId());
            finger.setOsVersion(identifyVersion.getVersion());
        }

        //region 设备硬件型号
        if( finger.getApp() == App.APP ){
            if(null!=jsonObject){
                finger.setModel(jsonObject.getString("model"));
                finger.setJsonSchema(JSON.toJSONString(jsonObject));
            }
        }else{
            finger.setAppFaker(AppFaker.parseUserAgent(userAgent));
        }
        //endregion

        finger.setBotFaker(Bot.parseUserAgent(userAgent));

        if(null!=jsonObject){
            finger.setJsonSchema(JSON.toJSONString(jsonObject));
        }
        return  finger;
    }

}